/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.osdtsystem.hierarchy;

import java.util.List;
import java.util.NoSuchElementException;
import org.osdtsystem.utils.Storage;

/**
 * Abstract class for simple hierarchies.
 * @param <H> the type of hierarchy classes
 * @author Matthias Buch-Kromann
 */
public abstract class AbstractSimpleHierarchy<H extends HClass> extends AbstractHierarchy<H> {
    public AbstractSimpleHierarchy(Class<H> type, Storage storage) {
        super(type, storage);
    }

    @Override
    public final int dimensions() {
        return 1;
    }

    @Override
    public final HClass componentClass(H hclass, int dimension) throws IllegalArgumentException {
        if (dimension != 0)
            throw new IllegalArgumentException("Illegal relative component dimension: must be 0, but was " + dimension);
        return hclass;
    }

    @Override
    public final HClass componentClassAtDepth(H hclass, int dimension, int depth) throws IllegalArgumentException {
        if (dimension != 0)
            throw new IllegalArgumentException("Illegal relative component dimension: must be 0, but was " + dimension);
        return hclass.depth() <= depth
                ? hclass
                : superclass(hclass, depth);
    }

    @Override
    public final int[] subclassComponents(H hclass, H subclass, int offset) {
        if (hclass.equals(subclass)) {
            return new int[0];
        } else {
            int[] components = {offset};
            return components;
        }
    }

    @Override
    public HierarchyIterator<H> hierarchyIterator(H root, H subclass) {
        return new SimpleHierarchyIterator<H>(this, root, subclass);
    }
    
    /**
     * The unique super class for a hierarchy class at a given depth. If the depth
     * is larger than or equal to the depth of the hierarchy class, the hierarchy class
     * itself is returned.
     * @param hclass the hierarchy class
     * @param depth the maximum depth of the super class
     * @return the unique super class at this depth
     */
    public abstract H superclass(H hclass, int depth);
}
